/**
 * 网络请求工具
 * 基于fetch API封装的请求函数，支持统一错误处理和JSON响应解析
 */

import type { ApiResponse } from '@/types/api';

/** API基础URL配置 */
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8000/api/';

/** 请求错误类 */
export class RequestError extends Error {
  constructor(
    public code: number,
    message: string,
    public errors?: Record<string, string[]>
  ) {
    super(message);
    this.name = 'RequestError';
  }
}

/** 请求配置选项 */
interface RequestOptions extends RequestInit {
  params?: Record<string, any>;
}

/**
 * 构建URL查询参数
 */
const buildQueryString = (params: Record<string, any>): string => {
  const searchParams = new URLSearchParams();
  Object.entries(params).forEach(([key, value]) => {
    if (value !== undefined && value !== null) {
      searchParams.append(key, String(value));
    }
  });
  return searchParams.toString();
};

/**
 * 核心请求函数
 * @param endpoint - API端点路径
 * @param options - 请求配置选项
 * @returns Promise<T> - 返回解析后的数据
 */
export const request = async <T = any>(
  endpoint: string,
  options: RequestOptions = {}
): Promise<T> => {
  const { params, ...fetchOptions } = options;

  // 构建完整URL
  let url = `${API_BASE_URL}${endpoint}`;
  if (params) {
    const queryString = buildQueryString(params);
    if (queryString) url += `?${queryString}`;
  }

  // 设置默认请求头
  const headers: HeadersInit = {
    'Content-Type': 'application/json',
    ...fetchOptions.headers,
  };

  try {
    const response = await fetch(url, {
      ...fetchOptions,
      headers,
    });

    // 解析JSON响应
    const data: ApiResponse<T> = await response.json();

    // 检查业务状态码
    if (data.code !== 200) {
      throw new RequestError(data.code, data.message, data.errors);
    }

    return data.data;
  } catch (error) {
    // 处理网络错误
    if (error instanceof RequestError) {
      throw error;
    }
    
    if (error instanceof TypeError) {
      throw new RequestError(0, '网络连接失败，请检查网络设置');
    }

    throw new RequestError(500, '请求失败，请稍后重试');
  }
};

/**
 * GET请求
 */
export const get = <T = any>(endpoint: string, params?: Record<string, any>): Promise<T> =>
  request<T>(endpoint, { method: 'GET', params });

/**
 * POST请求
 */
export const post = <T = any>(endpoint: string, body?: any): Promise<T> =>
  request<T>(endpoint, {
    method: 'POST',
    body: body ? JSON.stringify(body) : undefined,
  });

/**
 * PUT请求
 */
export const put = <T = any>(endpoint: string, body?: any): Promise<T> =>
  request<T>(endpoint, {
    method: 'PUT',
    body: body ? JSON.stringify(body) : undefined,
  });

/**
 * DELETE请求
 */
export const del = <T = any>(endpoint: string): Promise<T> =>
  request<T>(endpoint, { method: 'DELETE' });
